package com.xzzz.irda.guardcat.core.metric.system;

import com.sun.management.OperatingSystemMXBean;
import com.sun.management.UnixOperatingSystemMXBean;
import com.xzzz.common.base.util.SystemUtil;

import java.io.Serializable;
import java.lang.management.ManagementFactory;

/**
 * 操作系统信息
 *
 * @author xzzz
 * @since 1.0.0
 */
public class OperatingSystemInfo implements Serializable {
    private static final long serialVersionUID = 1L;

    /**
     * 用户名
     */
    private String userName;

    /**
     * 用户主目录
     */
    private String userHome;

    /**
     * 用户当前工作目录
     */
    private String userDir;

    /**
     * 操作系统名称, 等价于：System.getProperty("os.name")
     */
    private String name;

    /**
     * 操作系统架构, 等价于：System.getProperty("os.arch")
     */
    private String architecture;

    /**
     * 操作系统版本
     * <p>
     * 等价于：System.getProperty("os.version")
     */
    private String version;

    /**
     * 当前 IP 地址
     */
    private String ipAddress;

    /**
     * Java 虚拟机可用的处理器核数, 等价于: {@link Runtime#availableProcessors()}
     */
    private int availableProcessors;

    /**
     * 提交的虚拟内存总量【单位：KB】
     * 可供运行进程使用的虚拟内存量，如果不支持此操作，则 -1 。
     * <p>
     * 1 字节(Byte) = 8 位(bit)
     * 1 KB(Kilobyte，千字节) = 1024 B
     * 1 MB(Megabyte，兆字节) = 1024 KB
     * 1 GB(Gigabyte，吉字节，千兆) = 1024 MB
     * 1 TB(Trillionbyte，万亿字节，太字节) = 1024 GB
     */
    private long committedVirtualMemorySize;

    /**
     * 总的物理内存总量【单位：KB】
     */
    private long totalPhysicalMemorySize;

    /**
     * 空闲物理内存总量【单位：KB】
     */
    private long freePhysicalMemorySize;

    /**
     * 交换空间总量【单位：KB】
     */
    private long totalSwapSpaceSize;

    /**
     * 空闲交换空间总量【单位：KB】
     */
    private long freeSwapSpaceSize;

    /**
     * Java 虚拟机的进程使用的 CPU 时间【单位：纳秒】
     * 1 秒 = 1000 毫秒
     * 1 毫秒 = 1000 微秒
     * 1 微秒 = 1000 纳秒
     */
    private long processCpuTime;

    /**
     * 整个系统的 CPU 负载【CPU 的使用率】
     */
    private double systemCpuLoad;

    /**
     * java 虚拟机进程的 CPU 负载【CPU 的使用率】
     */
    private double processCpuLoad;

    /**
     * 最后一分钟的系统负载平均值。
     */
    private double systemLoadAverage;

    /**
     * 最大文件描述符数
     */
    private long maxFileDescriptorCount;

    /**
     * 打开文件描述符数
     */
    private long openFileDescriptorCount;

    /**
     * 将构造器私有化
     */
    private OperatingSystemInfo() {
    }

    /**
     * 获取操作系统信息
     *
     * @return OperatingSystemInfo 操作系统信息
     */
    public static OperatingSystemInfo getOperatingSystemInfo() {
        OperatingSystemInfo operatingSystemInfo = new OperatingSystemInfo();

        OperatingSystemMXBean operatingSystemMxBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
        operatingSystemInfo.userName = System.getProperty("user.name");
        operatingSystemInfo.userHome = System.getProperty("user.home");
        operatingSystemInfo.userDir = System.getProperty("user.dir");
        operatingSystemInfo.name = operatingSystemMxBean.getName();
        operatingSystemInfo.architecture = operatingSystemMxBean.getArch();
        operatingSystemInfo.version = operatingSystemMxBean.getVersion();
        operatingSystemInfo.ipAddress = SystemUtil.getIp();
        operatingSystemInfo.availableProcessors = operatingSystemMxBean.getAvailableProcessors();
        operatingSystemInfo.committedVirtualMemorySize = operatingSystemMxBean.getCommittedVirtualMemorySize() / 1024;
        operatingSystemInfo.totalPhysicalMemorySize = operatingSystemMxBean.getTotalPhysicalMemorySize() / 1024;
        operatingSystemInfo.freePhysicalMemorySize = operatingSystemMxBean.getFreePhysicalMemorySize() / 1024;
        operatingSystemInfo.totalSwapSpaceSize = operatingSystemMxBean.getTotalSwapSpaceSize() / 1024;
        operatingSystemInfo.freeSwapSpaceSize = operatingSystemMxBean.getFreeSwapSpaceSize() / 1024;
        operatingSystemInfo.processCpuTime = operatingSystemMxBean.getProcessCpuTime() / 1000 / 1000;
        operatingSystemInfo.systemCpuLoad = operatingSystemMxBean.getSystemCpuLoad();
        operatingSystemInfo.processCpuLoad = operatingSystemMxBean.getProcessCpuLoad();
        operatingSystemInfo.systemLoadAverage = operatingSystemMxBean.getSystemLoadAverage();

        if (operatingSystemMxBean instanceof UnixOperatingSystemMXBean) {
            UnixOperatingSystemMXBean unixOperatingSystemMxBean = (UnixOperatingSystemMXBean) operatingSystemMxBean;
            operatingSystemInfo.maxFileDescriptorCount = unixOperatingSystemMxBean.getMaxFileDescriptorCount();
            operatingSystemInfo.openFileDescriptorCount = unixOperatingSystemMxBean.getOpenFileDescriptorCount();
        }

        return operatingSystemInfo;
    }

    public String getUserName() {
        return userName;
    }

    public String getUserHome() {
        return userHome;
    }

    public String getUserDir() {
        return userDir;
    }

    public String getName() {
        return name;
    }

    public String getArchitecture() {
        return architecture;
    }

    public String getVersion() {
        return version;
    }

    public String getIpAddress() {
        return ipAddress;
    }

    public int getAvailableProcessors() {
        return availableProcessors;
    }

    public long getCommittedVirtualMemorySize() {
        return committedVirtualMemorySize;
    }

    public long getTotalPhysicalMemorySize() {
        return totalPhysicalMemorySize;
    }

    public long getFreePhysicalMemorySize() {
        return freePhysicalMemorySize;
    }

    public long getTotalSwapSpaceSize() {
        return totalSwapSpaceSize;
    }

    public long getFreeSwapSpaceSize() {
        return freeSwapSpaceSize;
    }

    public long getProcessCpuTime() {
        return processCpuTime;
    }

    public double getSystemCpuLoad() {
        return systemCpuLoad;
    }

    public double getProcessCpuLoad() {
        return processCpuLoad;
    }

    public double getSystemLoadAverage() {
        return systemLoadAverage;
    }

    public long getMaxFileDescriptorCount() {
        return maxFileDescriptorCount;
    }

    public long getOpenFileDescriptorCount() {
        return openFileDescriptorCount;
    }

    @Override
    public String toString() {
        return "操作系统信息{" +
                "用户名='" + userName + '\'' +
                ", 用户主目录='" + userHome + '\'' +
                ", 用户当前工作目录='" + userDir + '\'' +
                ", 名称='" + name + '\'' +
                ", 架构='" + architecture + '\'' +
                ", 版本='" + version + '\'' +
                ", IP地址='" + ipAddress + '\'' +
                ", 可用处理器核数=" + availableProcessors +
                ", 提交的虚拟内存大小=" + committedVirtualMemorySize +
                ", 总物理内存大小=" + totalPhysicalMemorySize +
                ", 空闲物理内存大小=" + freePhysicalMemorySize +
                ", 总的交换空间大小=" + totalSwapSpaceSize +
                ", 空闲的交换空间大小=" + freeSwapSpaceSize +
                ", JVM使用CPU的时间大小=" + processCpuTime +
                ", 系统的CPU负载=" + systemCpuLoad +
                ", JVM的CPU负载=" + processCpuLoad +
                ", 系统最后一分钟的平均负载=" + systemLoadAverage +
                ", 最大文件描述符数量=" + maxFileDescriptorCount +
                ", 打开文件描述符数量=" + openFileDescriptorCount +
                '}';
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        System.out.println(OperatingSystemInfo.getOperatingSystemInfo());
        System.out.println(System.currentTimeMillis() - startTime);

        System.out.println("\n\r");
        System.out.println(System.getProperties());
    }
}
